﻿package com.rbac.system.service.impl;

import com.rbac.system.entity.Menu;
import com.rbac.system.entity.Permission;
import com.rbac.system.entity.RoleMenu;
import com.rbac.system.entity.RolePermission;
import com.rbac.system.mapper.MenuMapper;
import com.rbac.system.mapper.PermissionMapper;
import com.rbac.system.mapper.RoleMenuMapper;
import com.rbac.system.mapper.RolePermissionMapper;
import com.rbac.system.service.MenuPermissionMappingService;
import com.rbac.system.service.PermissionDependencyService;
import com.rbac.system.service.PermissionSyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 权限同步服务实现
 */
@Service
public class PermissionSyncServiceImpl implements PermissionSyncService {
    
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    
    @Autowired
    private MenuMapper menuMapper;
    
    @Autowired
    private PermissionMapper permissionMapper;
    
    @Autowired
    private PermissionDependencyService permissionDependencyService;
    
    @Autowired
    private MenuPermissionMappingService menuPermissionMappingService;
    
    @Override
    @Transactional
    public int syncMenusForPermissions(Long roleId, List<Long> permissionIds) {
        if (permissionIds == null || permissionIds.isEmpty()) {
            return 0;
        }
        
        // 获取权限编码
        List<String> permissionCodes = getPermissionCodes(permissionIds);
        
        // 获取相关菜单
        Set<Long> relatedMenuIds = getRelatedMenusByPermissionCodes(permissionCodes);
        
        if (relatedMenuIds.isEmpty()) {
            return 0;
        }
        
        // 解析菜单依赖，包含父级菜单
        Set<Long> allMenuIds = permissionDependencyService.resolveMenuDependencies(new ArrayList<>(relatedMenuIds));
        
        // 获取角色已有的菜单，避免重复分配
        List<RoleMenu> existingRoleMenus = roleMenuMapper.selectByRoleId(roleId);
        Set<Long> existingMenuIds = existingRoleMenus.stream()
                .map(RoleMenu::getMenuId)
                .collect(Collectors.toSet());
        
        int syncedCount = 0;
        for (Long menuId : allMenuIds) {
            if (!existingMenuIds.contains(menuId)) {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setRoleId(roleId);
                roleMenu.setMenuId(menuId);
                roleMenu.setCreateTime(LocalDateTime.now());
                roleMenu.setDeleted(0);
                roleMenuMapper.insert(roleMenu);
                syncedCount++;
            }
        }
        
        return syncedCount;
    }
    
    @Override
    @Transactional
    public int syncPermissionsForMenus(Long roleId, List<Long> menuIds) {
        if (menuIds == null || menuIds.isEmpty()) {
            return 0;
        }
        
        // 使用MenuPermissionMappingService获取相关权限
        Set<Long> relatedPermissionIds = menuPermissionMappingService.getPermissionsByMenus(menuIds);
        
        if (relatedPermissionIds.isEmpty()) {
            return 0;
        }
        
        // 解析权限依赖，包含父级权限
        Set<Long> allPermissionIds = permissionDependencyService.resolvePermissionDependencies(new ArrayList<>(relatedPermissionIds));
        
        // 获取角色已有的权限，避免重复分配
        List<RolePermission> existingRolePermissions = rolePermissionMapper.selectByRoleId(roleId);
        Set<Long> existingPermissionIds = existingRolePermissions.stream()
                .map(RolePermission::getPermissionId)
                .collect(Collectors.toSet());
        
        int syncedCount = 0;
        for (Long permissionId : allPermissionIds) {
            if (!existingPermissionIds.contains(permissionId)) {
                RolePermission rolePermission = new RolePermission();
                rolePermission.setRoleId(roleId);
                rolePermission.setPermissionId(permissionId);
                rolePermission.setCreateTime(LocalDateTime.now());
                rolePermission.setDeleted(0);
                rolePermissionMapper.insert(rolePermission);
                syncedCount++;
            }
        }
        
        return syncedCount;
    }
    
    @Override
    public Set<Long> getRelatedMenusByPermissionCodes(List<String> permissionCodes) {
        Set<Long> menuIds = new HashSet<>();
        
        for (String permissionCode : permissionCodes) {
            // 简化的权限菜单映射逻辑
            menuIds.addAll(mapPermissionCodeToMenuIds(permissionCode));
        }
        
        return menuIds;
    }
    
    @Override
    public Set<Long> getRelatedPermissionsByMenuIds(List<Long> menuIds) {
        return menuPermissionMappingService.getPermissionsByMenus(menuIds);
    }
    
    @Override
    @Transactional
    public String checkAndFixRolePermissionConsistency(Long roleId) {
        StringBuilder result = new StringBuilder();
        
        // 获取角色的所有菜单
        List<RoleMenu> roleMenus = roleMenuMapper.selectByRoleId(roleId);
        List<Long> menuIds = roleMenus.stream().map(RoleMenu::getMenuId).collect(Collectors.toList());
        
        // 获取角色的所有权限
        List<RolePermission> rolePermissions = rolePermissionMapper.selectByRoleId(roleId);
        List<Long> permissionIds = rolePermissions.stream().map(RolePermission::getPermissionId).collect(Collectors.toList());
        
        // 检查菜单对应的权限是否完整
        int syncedPermissions = syncPermissionsForMenus(roleId, menuIds);
        if (syncedPermissions > 0) {
            result.append("为菜单补充了 ").append(syncedPermissions).append(" 个权限; ");
        }
        
        // 检查权限对应的菜单是否完整
        int syncedMenus = syncMenusForPermissions(roleId, permissionIds);
        if (syncedMenus > 0) {
            result.append("为权限补充了 ").append(syncedMenus).append(" 个菜单; ");
        }
        
        if (result.length() == 0) {
            result.append("权限菜单一致性检查通过，无需修复");
        }
        
        return result.toString();
    }
    
    /**
     * 获取权限编码列表
     */
    private List<String> getPermissionCodes(List<Long> permissionIds) {
        List<String> permissionCodes = new ArrayList<>();
        for (Long permissionId : permissionIds) {
            Permission permission = permissionMapper.selectById(permissionId);
            if (permission != null && permission.getPermissionCode() != null) {
                permissionCodes.add(permission.getPermissionCode());
            }
        }
        return permissionCodes;
    }
    
    /**
     * 简化的权限编码到菜单ID的映射
     */
    private Set<Long> mapPermissionCodeToMenuIds(String permissionCode) {
        Set<Long> menuIds = new HashSet<>();
        
        try {
            // 基于权限编码的命名规范进行映射
            if (permissionCode.startsWith("user:")) {
                // 用户相关权限 -> 个人中心菜单
                menuIds.addAll(findMenusByCodeOrPath("profile", "/profile"));
            } else if (permissionCode.startsWith("admin:user")) {
                // 用户管理权限 -> 用户管理菜单
                menuIds.addAll(findMenusByCodeOrPath("user-management", "/system/user"));
                menuIds.addAll(findMenusByCodeOrPath("system", "/system"));
            } else if (permissionCode.startsWith("admin:role")) {
                // 角色管理权限 -> 角色管理菜单
                menuIds.addAll(findMenusByCodeOrPath("role-management", "/system/role"));
                menuIds.addAll(findMenusByCodeOrPath("system", "/system"));
            } else if (permissionCode.startsWith("admin:menu")) {
                // 菜单管理权限 -> 菜单管理菜单
                menuIds.addAll(findMenusByCodeOrPath("menu-management", "/system/menu"));
                menuIds.addAll(findMenusByCodeOrPath("system", "/system"));
            } else if (permissionCode.startsWith("admin:permission")) {
                // 权限管理权限 -> 权限管理菜单
                menuIds.addAll(findMenusByCodeOrPath("permission-management", "/system/permission"));
                menuIds.addAll(findMenusByCodeOrPath("system", "/system"));
            }
        } catch (Exception e) {
            // 忽略映射错误
        }
        
        return menuIds;
    }
    
    /**
     * 根据菜单编码或路径查找菜单ID
     */
    private Set<Long> findMenusByCodeOrPath(String code, String path) {
        Set<Long> menuIds = new HashSet<>();
        
        try {
            List<Menu> allMenus = menuMapper.selectList(new Menu());
            for (Menu menu : allMenus) {
                boolean matches = false;
                
                // 检查菜单编码
                if (menu.getMenuCode() != null && menu.getMenuCode().equals(code)) {
                    matches = true;
                }
                
                // 检查菜单路径
                if (menu.getPath() != null && menu.getPath().equals(path)) {
                    matches = true;
                }
                
                if (matches) {
                    menuIds.add(menu.getId());
                }
            }
        } catch (Exception e) {
            // 忽略查询错误
        }
        
        return menuIds;
    }
}


